package org.javaforever.cookieshop.serviceimpl;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.cookieshop.dao.CustOrderDao;
import org.javaforever.cookieshop.dao.OrderItemDao;
import org.javaforever.cookieshop.domain.CustOrderBean;
import org.javaforever.cookieshop.domain.GoodsBean;
import org.javaforever.cookieshop.domain.OrderItemBean;
import org.javaforever.cookieshop.domain.PageBean;
import org.javaforever.cookieshop.service.CustOrderService;
import org.javaforever.cookieshop.service.GoodsService;
import org.javaforever.cookieshop.service.OrderItemService;
import org.javaforever.cookieshop.service.UserService;
import org.javaforever.cookieshop.utils.DateUtil;
import org.javaforever.cookieshop.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;

@Service
public class CustOrderServiceImpl implements CustOrderService{
	@Autowired
	protected CustOrderDao dao;

	@Autowired
	protected OrderItemDao orderItemDao;

	@Autowired
	protected OrderItemService orderItemService;
	
	@Autowired
	protected UserService userService;
	
	@Autowired
	protected GoodsService goodsService;
	
	@PersistenceContext
	protected EntityManager entityManager;

	@Override
	public void activateAllCustOrders(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.activateCustOrder(id);
        }
	}

	@Override
	public Boolean activateCustOrder(Long id) throws Exception{
        dao.activateCustOrder(id);
        return true;
	}

	@Override
	@Transactional
	public Long addCustOrder(CustOrderBean custOrder) throws Exception{
		CustOrderBean newOrder = dao.saveAndFlush(custOrder);
        return newOrder.getId();
	}

	@Override
	@Transactional
	public Boolean assignOrderItemsToCustOrder(Long custOrderId,String orderItemIds) throws Exception{
        String [] orderItemIdsArr = orderItemIds.split(",");
        for (int i = 0; i < orderItemIdsArr.length; i++ ){
        Long orderItemId = Long.parseLong(orderItemIdsArr[i]);
        Integer success = dao.assignOrderItemToCustOrder(custOrderId,orderItemId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	public void cloneAllCustOrders(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            cloneCustOrder(id);
        }
	}

	@Override
	public Boolean cloneCustOrder(Long id) throws Exception{
        CustOrderBean custOrder = dao.findCustOrderFullInfoById(id);
        
        String name = custOrder.getName();
        String shortName = name;
        if (name.contains("_") && StringUtil.isInteger(name.substring(name.lastIndexOf('_')+1,name.length()))) {
            shortName = name.substring(0,name.lastIndexOf('_'));
        }
        List<CustOrderBean> names = dao.searchCustOrderIndexedNamesByShortName(shortName);
        int indexNum = 1;
        for (CustOrderBean custOrder0:names) {
            String _name = custOrder0.getName();
            if (_name.contains("_") && StringUtil.isInteger(_name.substring(_name.lastIndexOf('_')+1,_name.length()))) {
                int index = Integer.valueOf(_name.substring(_name.lastIndexOf('_')+1,_name.length()));
                if (index >= indexNum) {
                    indexNum = index + 1;
                }
            }
        }
        String indexName = shortName + "_" + indexNum;
        CustOrderBean custOrder1 = custOrder.clone();
        custOrder1.setId(null);
        custOrder1.setName(indexName);
        addCustOrder(custOrder1);
        return true;
	}

	@Override
	public Integer countActiveCustOrderRecords() throws Exception{
        return dao.countActiveCustOrderRecords();
	}

	@Override
	public Integer countSearchCustOrdersByFieldsRecords(CustOrderBean custOrder) throws Exception{
        String jpql = "select count(*) as countNum from CustOrderBean c where 1=1 ";
        if (custOrder.getName() != null) {
            jpql += " and c.name like CONCAT('%', '"+custOrder.getName()+"','%')";
        }
        if (custOrder.getActive() != null) {
            jpql += " and c.active = "+custOrder.getActive();
        }
        if (custOrder.getTotal() != null && custOrder.getTotal() != 0) {
            jpql += " and abs(c.total - "+custOrder.getTotal()+") < 0.0001";
        }
        if (custOrder.getAmount() != null && custOrder.getAmount() != 0) {
            jpql += " and c.amount = "+custOrder.getAmount();
        }
        if (custOrder.getStatus() != null) {
            jpql += " and c.status = "+custOrder.getStatus();
        }
        if (custOrder.getPaytype() != null) {
            jpql += " and c.paytype = "+custOrder.getPaytype();
        }
        if (custOrder.getPhone() != null) {
            jpql += " and c.phone like CONCAT('%', '"+custOrder.getPhone()+"','%')";
        }
        if (custOrder.getAddress() != null) {
            jpql += " and c.address like CONCAT('%', '"+custOrder.getAddress()+"','%')";
        }
        if (custOrder.getOrderDateTime() != null) {
            jpql += " and date(c.orderDateTime) = date('"+DateUtil.utilDateTimeToString(custOrder.getOrderDateTime())+"')";
        }
        if (custOrder.getUser() != null) {
            jpql += " and c.user = "+custOrder.getUser();
        }
        Query query = entityManager.createQuery(jpql);
        Long count = (Long) query.getSingleResult();
        return count.intValue();
	}

	@Override
	public void deleteAllCustOrders(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.deleteCustOrder(id);
        }
	}

	@Override
	public Boolean deleteCustOrder(Long id) throws Exception{
        dao.deleteCustOrder(id);
        return true;
	}

	@Override
	public CustOrderBean findCustOrderById(Long id) throws Exception{
        return dao.findCustOrderById(id);
	}

	@Override
	public CustOrderBean findCustOrderByName(String name) throws Exception{
        return dao.findCustOrderByName(name);
	}

	@Override
	public Set<OrderItemBean> listActiveCustOrderOrderItemsUsingCustOrderId(Long custOrderId) throws Exception{
        Set<OrderItemBean> _set = new TreeSet<OrderItemBean>();
        _set.addAll(orderItemDao.listActiveCustOrderOrderItemsUsingCustOrderId(custOrderId));
        return _set;
	}

	@Override
	public List<CustOrderBean> listActiveCustOrders() throws Exception{
        return dao.listActiveCustOrders();
	}

	@Override
	public List<CustOrderBean> listAllCustOrders() throws Exception{
        return dao.listAllCustOrders();
	}

	@Override
	public Set<OrderItemBean> listAvailableActiveCustOrderOrderItemsUsingCustOrderId(Long custOrderId) throws Exception{
        Set<OrderItemBean> fullset = new TreeSet<OrderItemBean>();
        fullset.addAll(orderItemService.listActiveOrderItems());
        Set<OrderItemBean> set = listActiveCustOrderOrderItemsUsingCustOrderId(custOrderId);
        fullset.removeAll(set);	
        return fullset;
	}

	@Override
	@Transactional
	public Boolean revokeOrderItemsFromCustOrder(Long custOrderId,String orderItemIds) throws Exception{
        String [] orderItemIdsArr = orderItemIds.split(",");
        for (int i = 0; i < orderItemIdsArr.length; i++ ){
        Long orderItemId = Long.parseLong(orderItemIdsArr[i]);
        Integer success = dao.revokeOrderItemFromCustOrder(custOrderId,orderItemId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	public List<CustOrderBean> searchCustOrdersByFields(CustOrderBean custOrder) throws Exception{
        String jpql = "from CustOrderBean c where 1=1 ";
        if (custOrder.getName() != null) {
            jpql += " and c.name like CONCAT('%', '"+custOrder.getName()+"','%')";
        }
        if (custOrder.getActive() != null) {
            jpql += " and c.active = "+custOrder.getActive();
        }
        if (custOrder.getTotal() != null && custOrder.getTotal() != 0) {
            jpql += " and abs(c.total - "+custOrder.getTotal()+") < 0.0001";
        }
        if (custOrder.getAmount() != null && custOrder.getAmount() != 0) {
            jpql += " and c.amount = "+custOrder.getAmount();
        }
        if (custOrder.getStatus() != null) {
            jpql += " and c.status = "+custOrder.getStatus();
        }
        if (custOrder.getPaytype() != null) {
            jpql += " and c.paytype = "+custOrder.getPaytype();
        }
        if (custOrder.getPhone() != null) {
            jpql += " and c.phone like CONCAT('%', '"+custOrder.getPhone()+"','%')";
        }
        if (custOrder.getAddress() != null) {
            jpql += " and c.address like CONCAT('%', '"+custOrder.getAddress()+"','%')";
        }
        if (custOrder.getOrderDateTime() != null) {
            jpql += " and date(c.orderDateTime) = date('"+DateUtil.utilDateTimeToString(custOrder.getOrderDateTime())+"')";
        }
        if (custOrder.getUser() != null) {
            jpql += " and c.user = "+custOrder.getUser();
        }
        Query query = entityManager.createQuery(jpql);
        List<CustOrderBean> results = query.getResultList();
        return results;
	}

	@Override
	public List<CustOrderBean> searchCustOrdersByFieldsByPage(CustOrderBean custOrder,Integer pagesize,Integer pagenum) throws Exception{
        Integer start = (pagenum-1)*pagesize;
        Integer limit = pagesize;
        String jpql = "from CustOrderBean c where 1=1 ";
        if (custOrder.getName() != null) {
            jpql += " and c.name like CONCAT('%', '"+custOrder.getName()+"','%')";
        }
        if (custOrder.getActive() != null) {
            jpql += " and c.active = "+custOrder.getActive();
        }
        if (custOrder.getTotal() != null && custOrder.getTotal() != 0) {
            jpql += " and abs(c.total - "+custOrder.getTotal()+") < 0.0001";
        }
        if (custOrder.getAmount() != null && custOrder.getAmount() != 0) {
            jpql += " and c.amount = "+custOrder.getAmount();
        }
        if (custOrder.getStatus() != null) {
            jpql += " and c.status = "+custOrder.getStatus();
        }
        if (custOrder.getPaytype() != null) {
            jpql += " and c.paytype = "+custOrder.getPaytype();
        }
        if (custOrder.getPhone() != null) {
            jpql += " and c.phone like CONCAT('%', '"+custOrder.getPhone()+"','%')";
        }
        if (custOrder.getAddress() != null) {
            jpql += " and c.address like CONCAT('%', '"+custOrder.getAddress()+"','%')";
        }
        if (custOrder.getOrderDateTime() != null) {
            jpql += " and date(c.orderDateTime) = date('"+DateUtil.utilDateTimeToString(custOrder.getOrderDateTime())+"')";
        }
        if (custOrder.getUser() != null) {
            jpql += " and c.user = "+custOrder.getUser();
        }
        Query query = entityManager.createQuery(jpql);
        query.setFirstResult(start); // 设置起始位置
        query.setMaxResults(limit); // 设置返回结果数量
        List<CustOrderBean> results = query.getResultList();
        return results;
	}

	public void setDao(CustOrderDao dao){
		this.dao = dao;
	}

	public void setOrderItemService(OrderItemService orderItemService){
		this.orderItemService = orderItemService;
	}

	@Override
	public void softDeleteAllCustOrders(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.softDeleteCustOrder(id);
        }
	}

	@Override
	public boolean softDeleteCustOrder(Long id) throws Exception{
        dao.softDeleteCustOrder(id);
        return true;
	}

	@Override
	public Boolean toggleCustOrder(Long id) throws Exception{
        dao.toggleCustOrder(id);
        return true;
	}

	@Override
	public Boolean toggleOneCustOrder(Long id) throws Exception{
        CustOrderBean custOrder = dao.findCustOrderById(id);
        if (custOrder.getActive()==false) {
            dao.toggleCustOrder(id);
        }
        else {
            Integer count = dao.countActiveCustOrderRecords();
            if (count > 1){
                dao.toggleCustOrder(id);
            }
        }
        return true;
	}

	@Override
	@Transactional
	public Boolean updateCustOrder(CustOrderBean custOrder) throws Exception{
        entityManager.merge(custOrder);
        return true;
	}
	
	@Override
	@Transactional
	public Boolean updateCustOrderStatus(Long id, Integer status) throws Exception{
        CustOrderBean order = findCustOrderById(id);
        order.setStatus(status);
        updateCustOrder(order);
        return true;
	}
	
	@Override
    public PageBean getOrderPage(int status,int pageNumber) throws Exception {
        PageBean p = new PageBean();
        p.setPageNumber(pageNumber);
        int pageSize = 10;
        int totalCount = 0;
        totalCount = getOrderCount(status);
        p.SetPageSizeAndTotalCount(pageSize, totalCount);
        List list=null;
        list = selectOrderList(status, pageNumber, pageSize);
        for(CustOrderBean o :(List<CustOrderBean>)list) {
        	List<OrderItemBean> l  = orderItemDao.selectAllItem(o.getId());
        	for (OrderItemBean ol: l) {
        		GoodsBean g = goodsService.findGoodsById(ol.getGoods());
        		ol.setGoodsBean(g);
        	}
        	o.setItemList(l);
        }
        p.setList(list);
        return p;
    }
    
    public int getOrderCount(int status) throws SQLException {
        if(status==0) {
            String jpql = "select count(*) from CustOrderBean o where o.active = true";
            Query query = entityManager.createQuery(jpql);
            Long count = (Long)query.getSingleResult();
            return count.intValue();
        }else {
        	String jpql = "select count(*) from CustOrderBean o where o.status=?1 and o.active = true";
            Query query = entityManager.createQuery(jpql);
            query.setParameter(1, status);
            Long count = (Long)query.getSingleResult();
            return count.intValue();
        }
    }
    
    public List<CustOrderBean> selectOrderList(int status, int pageNumber, int pageSize) throws Exception {
    	Integer start = (pageNumber-1)*pageSize;
    	Integer limit = pageSize;
    	if(status==0) {
            String jpql = "from CustOrderBean o where o.active=true order by o.orderDateTime desc";
            Query query = entityManager.createQuery(jpql);
            query.setFirstResult(start); // 设置起始位置
            query.setMaxResults(limit); // 设置返回结果数量
            List<CustOrderBean> results = (List<CustOrderBean>)query.getResultList();
            for (CustOrderBean o:results) {
            	o.setUserBean(userService.findUserById(o.getUser()));
            }
            return results;
        }else {
            String jpql = "from CustOrderBean o where o.active=true and o.status=?1 order by o.orderDateTime desc";
            Query query = entityManager.createQuery(jpql);
            query.setParameter(1, status);
            query.setFirstResult(start); // 设置起始位置
            query.setMaxResults(limit); // 设置返回结果数量
            List<CustOrderBean> results = (List<CustOrderBean>)query.getResultList();
            for (CustOrderBean o:results) {
            	o.setUserBean(userService.findUserById(o.getUser()));
            }
            return results;
        }
    }

	@Override
	@Transactional
	public Boolean submitCustOrder(CustOrderBean custOrder) throws Exception{
		custOrder.setActive(true);
		Long id = addCustOrder(custOrder);
		Integer serial = 1;
		for(OrderItemBean item : custOrder.getItemMap().values()) {
			item.setName("CustOrder"+id+"_"+serial);
			serial ++;
			item.setActive(true);
			item.setCustOrder(id);
			orderItemService.addOrderItem(item);
		}
		return true;
	}
}
